package com.shop.shopserver.provider;

import com.shop.shopcommon.token.CustomUser;
import com.shop.shopcommon.token.PhoneVerificationToken;
import com.shop.shopserver.service.PhoneUserDetailsService;
import com.shop.shopserver.service.impl.PhoneUserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.crypto.codec.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * 手机验证码登录认证提供者
 */
@Component
public class PhoneVerificationAuthenticationProvider implements AuthenticationProvider {

    private static final Logger logger = LoggerFactory.getLogger(PhoneVerificationAuthenticationProvider.class);

    @Autowired
    private PhoneUserDetailsService phoneUserDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        try {
            PhoneVerificationToken auth = (PhoneVerificationToken) authentication;

            // 校验输入是否为空
            if (auth == null || auth.getName() == null || auth.getCredentials() == null) {
                throw new AuthenticationServiceException("Invalid phone or verification code");
            }

            String phone = auth.getName();
            String verificationCode = (String) auth.getCredentials();

            // 加载用户信息
//            UserDetails user = phoneUserDetailsService.loadUserByUsername(phone);
            CustomUser user = phoneUserDetailsService.loadUserByUsername(phone);
            if (user == null) {
                logger.warn("User not found for phone: {}", phone);
                return null; // 用户不存在，返回 null
            }

            // 验证验证码
            if (!isVerificationCodeValid(user, verificationCode)) {
                logger.warn("Invalid verification code for phone: {}", phone);
                return null; // 验证码无效，返回 null
            }

            // 验证通过，返回有效的 Authentication 对象，认证成功的令牌
            PhoneVerificationToken result = new PhoneVerificationToken(user, authentication.getCredentials(), user.getAuthorities());
//            result.setDetails(auth.getDetails());
            // 创建一个 Map 并添加键值对 为Details填充id
            Map<String, Long> map = new HashMap<>();
            map.put("id", user.getId());
            result.setDetails(map);
            return result;

        } catch (Exception e) {
            logger.error("Authentication failed: {}", e.getMessage(), e);
            throw new AuthenticationServiceException("Authentication failed", e);
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return PhoneVerificationToken.class.isAssignableFrom(authentication);
    }

    /**
     * 验证验证码是否有效
     */
    private boolean isVerificationCodeValid(UserDetails user, String verificationCode) {
        if (user.getPassword() == null) {
            logger.warn("UserDetails password is null");
            return false;
        }

        // 恒定时间比较，防止时间攻击
        byte[] codeBytes = verificationCode.getBytes();
        byte[] passwordBytes = user.getPassword().getBytes();
        return Arrays.equals(Hex.encode(codeBytes), Hex.encode(passwordBytes));
    }
}
